/*
 * semaphore.c
 *
 *  Created on: Apr 9, 2011
 *      Author: xozyain
 */

#include "types.h"
#include "user.h"

//#include "stat.h"

#include "semaphore.h"

struct semaphore * semaphore_create(int initial_semaphore_value){
	struct semaphore * s;

	if (!(s = (struct semaphore *)malloc(sizeof(struct semaphore)))){
		printf(2,"semaphore_create: malloc error\n");
		exit();
	}
	s->S1 = binary_sem_create();
	s->S2 = binary_sem_create();

	//S2=min(1, init_semaphore_vallue)
	if (initial_semaphore_value < 1)
		binary_sem_down(s->S2);

	s->value = initial_semaphore_value;
	return s;
}

void sem_up(struct semaphore * sem){

	if (binary_sem_down(sem->S1) != 0){
		printf(2,"sem_up: down(S1): error\n");
		exit();
	}
	sem->value++;

	if(sem->value == 1){

		if (binary_sem_up(sem->S2) !=0){
			printf(2,"sem_up: up(S2): error\n");
			exit();
		}
	}

	if (binary_sem_up(sem->S1)!=0){
		printf(2,"sem_up: up(S1): error\n");
		exit();
	}
}

void sem_down(struct semaphore * sem){


	if (binary_sem_down(sem->S2) < 0){
		printf(2,"sem_down: down(S2): error\n");
		exit();
	}
	if (binary_sem_down(sem->S1) < 0){
		printf(2,"sem_down: down(S1): error\n");
		exit();
	}
	sem->value--;

	if (sem->value > 0)
		if (binary_sem_up(sem->S2)< 0){
			printf(2,"sem_down: up(S2): error\n");
			exit();
		}

	if (binary_sem_up(sem->S1)< 0){
		printf(2,"sem_down: up(S1): error\n");
		exit();
	}

}
